<?php


namespace App\Kuafu\Coupon\Service;


use App\Exceptions\BaseException;
use App\Kuafu\Activity\Enum\ActivityEnum;
use App\Kuafu\Activity\Model\ActivityModel;
use App\Kuafu\Activity\Service\ActivityService;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Coupon\Enum\CouponCacheEnum;
use App\Kuafu\Coupon\Enum\CouponCodeEnum;
use App\Kuafu\Coupon\Enum\CouponEnum;
use App\Kuafu\Coupon\Exceptions\CouponException;
use App\Kuafu\Coupon\Model\CouponModel;
use App\Kuafu\CustomerCoupon\Enum\CodeEnum;
use App\Kuafu\CustomerCoupon\Enum\CustomerCouponCodeEnum;
use App\Kuafu\CustomerCoupon\Model\CustomerCouponModel;
use App\Kuafu\CustomerCoupon\Service\CustomerEnableCouponService;
use App\Kuafu\Holiday\Service\HolidayService;
use App\Kuafu\Shop\Service\ShopService;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;

class PosEnableCouponService extends BaseService
{
    /**
     * @var array 已使用的优惠券列表
     */
    private array $usedCoupons = [];

    /**
     * @var array 不可用优惠券列表
     */
    private array $canNotUseCouponList = [];

    /**
     * 可用优惠券列表
     * @var
     */
    private array $canUseCouponList = [];

    /**
     * @return array
     */
    public function getCanNotUseCouponList(): array
    {
        return $this->canNotUseCouponList;
    }

    /**
     * @param array $canNotUseCouponList
     */
    public function setCanNotUseCouponList(array $canNotUseCouponList): void
    {
        $this->canNotUseCouponList = $canNotUseCouponList;
    }

    /**
     * @return mixed
     */
    public function getCanUseCouponList(): array
    {
        return $this->canUseCouponList;
    }

    /**
     * @param mixed $canUseCouponList
     */
    public function setCanUseCouponList(array $canUseCouponList): void
    {
        $this->canUseCouponList = $canUseCouponList;
    }

    /**
     * @var array 商品分摊信息
     */
    private array $productList = [];

    private $source;

    private $activityType;

    /**
     * @var int 已经优惠的金额
     */
    private $totalDiscount = 0;

    /**
     * @var int 已经抵扣的金额
     */
    private $totalCondition = 0;

    public function __construct($brandId, $shopId, $productList, $usedCouponList, $source, $activityType)
    {
        parent::__construct($brandId, $shopId);
        $this->usedCoupons  = $usedCouponList;
        $this->productList  = $productList;
        $this->activityType = $activityType;
        $this->source       = CodeEnum::CouponSourceChange($source);
    }

    /**
     * 检查输入的优惠券
     */
    public function checkUsedCoupon($couponIds)
    {
        $canUseCouponList     = $this->initPosCoupon()->getCanUseCouponList();
        $canUseCouponIds      = array_column($canUseCouponList, 'couponId');
        $usedCountValues      = array_count_values($couponIds);
        $newCanUsedCouponList = [];
        //校验输入优惠券
        foreach ($couponIds as $couponId) {
            if (!in_array($couponId, $canUseCouponIds)) {
                throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON);
            }
        }
        //组装优惠券信息
        foreach ($canUseCouponList as $key => $value) {
            if (in_array($value['couponId'], $couponIds)) {
                for ($i = 0; $i < $usedCountValues[$value['couponId']]; $i++) {
                    $newCanUsedCouponList[] = $value;
                }
            }
        }
        //获取已经使用的优惠券列表
        $this->usedCoupons = $newCanUsedCouponList;//可用优惠券列表
        $this->filterCustomerCoupon(CodeEnum::COUPON_INIT_TYPE_CHECK);
        return true;
    }


    /**
     * 获取所有优惠券信息
     * @param $userId
     */
    public function initPosCoupon()
    {
        $key = CouponCacheEnum::getPosActivityListCacheName($this->shopId);
        if (Redis::get($key)) {
            $this->canUseCouponList = json_decode(Redis::get($key), true);
        } else {
            //获取店铺基本基本信息
            $shopInfo = ShopService::getShopInfo($this->shopId);
            //查询满足当前店铺的部分店铺活动id集合
            $shopPartActivityIds = array_column(ActivityService::getActivityIdsByShopId($this->shopId,
                ActivityEnum::TYPE_POS_ACTIVITY, $this->brandId)->toArray(), 'id');
            //查询全部活动id集合
            $allActivityIds = array_column(ActivityService::getAllTypeActivityIds(ActivityEnum::TYPE_POS_ACTIVITY,
                $this->brandId)->toArray(), 'id');
            //查询满足店铺类型的活动id集合
            $shopTypeActivityIds = array_column(ActivityService::getTypeActivityIds($shopInfo['type'],
                ActivityEnum::TYPE_POS_ACTIVITY, $this->brandId)->toArray(), 'id');
            //合并所有的活动id集合
            $activityIds = array_unique(array_merge($shopPartActivityIds, $allActivityIds, $shopTypeActivityIds));
            //查询活动关联店铺信息
            $activityShopRel = ActivityService::getShopRelByActivityIds($activityIds)->keyBy('id')->toArray();
            //查询优惠券信息
            $couponList = ActivityService::getCouponRelByActivityIds($activityIds)->keyBy('id')->toArray();
            //todo 去重
            $couponList             = CommonService::arrayUnset($couponList, 'id');
            $this->canUseCouponList = array_values(CouponService::dateToChange($activityShopRel, $couponList));
            //todo redis
//            if (count($this->canUseCouponList) > 0) {
//                Redis::setex($key, rand(CouponEnum::ACTIVITY_CACHE_TIME_START, CouponEnum::ACTIVITY_CACHE_TIME_END),
//                    json_encode($this->canUseCouponList));
//            }
        }
        return $this;

    }

    /**
     *
     */
    public function filterCustomerCoupon($type = CodeEnum::COUPON_INIT_TYPE_SELECT)
    {
        //过滤不可用平台
        $this->filterCustomerCouponSource($type);
        //过滤有效期
        $this->filterCustomerCouponEffective($type);
        //过滤不可用店铺
        $this->filterCustomerCouponShop($type);
        //过滤活动叠加
//        $this->filterActivitySuperposition($type);
        //过滤优惠券不可用叠加
        $this->filterCustomerCouponSuperposition($type);
        //过滤使用超过最大限度
        $this->filterCustomerCouponUseMax($type);
        //过滤不可用日期
        $this->filterCustomerCouponDate($type);
        //过滤不可用时间
        $this->filterCustomerCouponTime($type);
        //过滤不可用产品
        $this->filterCustomerCouponProduct($type);
        //过滤金额不可用
        $this->filterCustomerCouponMoney($type);
        //重新组合返回数据
        $this->mergeCanUseCoupon();
        return $this;
    }

    public function mergeCanUseCoupon()
    {
        $usedCouponList         = $this->usedCoupons;
        $canUseCouponList       = $this->canUseCouponList;
        $canNotUseCouponList    = $this->canNotUseCouponList;
        $this->canUseCouponList = array_merge($usedCouponList, $canUseCouponList);
        $can                    = array_values(CommonService::arrayUnset($this->canUseCouponList, 'couponId'));
        $usedCouponListCodes    = array_column($usedCouponList, 'couponId');
        foreach ($canNotUseCouponList as $key => $value) {
            if (in_array($value['couponId'], $usedCouponListCodes)) {
                unset($canNotUseCouponList[$key]);
            }
        }
        $this->canUseCouponList    = $can;
        $this->canNotUseCouponList = array_values($canNotUseCouponList);
        return $this;
    }

    public function filterCustomerCouponEffective($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $time                = time();
        foreach ($canUseCouponList as $key => $value) {
            //使用有效期  1 固定时间 2 相对时间
            if ($value['useTimeType'] == 1) {
                //固定时间
                $startAt = $value['startAt'];
                $endAt   = $value['endAt'];
            } else {
                //相对时间
                $startAt = strtotime($value['createdAt']) + $value['startAt'] * 86400;
                $endAt   = strtotime($value['createdAt']) + ($value['startAt'] + $value['endAt']) * 86400;
            }
            if ($time <= $startAt || $time >= $endAt) {
                if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                    Log::info('pos使用优惠券错误--不在有效期范围内');
                    throw new CouponException(CouponCodeEnum::ERR_POS_USE_NOT_IN_EFFECTIVE,
                        $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_NOT_IN_EFFECTIVE]);
                } else {
                    $canNotUseCouponList[] = $value;
                    unset($canUseCouponList[$key]);
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }


    /**
     * 过滤不可用平台
     * @param $key
     * @param $value
     * @param $canUseCouponList
     */
    public function filterCustomerCouponSource($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        foreach ($canUseCouponList as $key => $value) {
            if ($value['availableSource'] > 0) {
                $decodeRules = CommonService::decodeRules($value['availableSource']);
                if (!in_array($this->source, $decodeRules)) {
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        Log::info('pos使用优惠券错误--平台错误');
                        throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_SOURCE,
                            $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_SOURCE]);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤活动不叠加
     * @param $type
     * @throws CouponException
     */
    public function filterActivitySuperposition($type)
    {
        $usedCoupons         = $this->usedCoupons;
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $activityIds         = array_unique(array_column($canUseCouponList, 'activityId'));
        foreach ($canUseCouponList as $key => $value) {
            if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                if ($value['isSuperposeActivity'] == CouponEnum::SUPERPOSE_ACTIVITY_NO && count($activityIds) > 1) {
                    Log::info('pos使用优惠券错误--活动不可叠加');
                    throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_ACTIVITY,
                        $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_ACTIVITY]);
                }
            } else {
                //判断已经使用的优惠券是否可以叠加活动
                foreach ($usedCoupons as $usedCoupon) {
                    if ($usedCoupon['isSuperposeActivity'] == CouponEnum::SUPERPOSE_ACTIVITY_NO) {
                        Log::info('pos使用优惠券错误--活动不可叠加');
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                        break;
                    }
                }
                if ($value['isSuperposeActivity'] == CouponEnum::SUPERPOSE_ACTIVITY_NO && count($activityIds) >= 1 && isset($canUseCouponList[$key])) {
                    Log::info('pos使用优惠券错误--活动不可叠加');
                    $canNotUseCouponList[] = $value;
                    unset($canUseCouponList[$key]);
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤优惠券不可叠加
     * @param $key
     * @param $value
     * @param $canUseCouponList
     */
    public function filterCustomerCouponSuperposition($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $usedCoupons         = $this->usedCoupons;//已经使用优惠券列表
        $couponIds           = array_unique(array_column($usedCoupons, 'couponId'));
        $canNotUseCouponList = $this->canNotUseCouponList;
        //判断已经选择的优惠券是否支持可叠加其他优惠券
        foreach ($canUseCouponList as $key => $value) {
            if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                if ($value['isSuperposeCoupon'] == CouponEnum::SUPERPOSE_COUPON_NO && count($couponIds) > 1) {
                    Log::info('pos使用优惠券错误--不可叠加');
                    throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_SUPERPOSITION,
                        $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_SUPERPOSITION]);
                }
            } else {
                //判断已经使用的优惠券是否可以叠加活动
                foreach ($usedCoupons as $usedCoupon) {
                    if ($usedCoupon['isSuperposeCoupon'] == CouponEnum::SUPERPOSE_COUPON_NO) {
                        Log::info('pos使用优惠券错误--不可叠加');
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                        break;
                    }
                }
                if ($value['isSuperposeCoupon'] == CouponEnum::SUPERPOSE_COUPON_NO && count($couponIds) >= 1 && isset($canUseCouponList[$key])) {
                    Log::info('pos使用优惠券错误--不可叠加');
                    $canNotUseCouponList[] = $value;
                    unset($canUseCouponList[$key]);
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤最大使用张数
     * @return $this
     */
    public function filterCustomerCouponUseMax($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $usedCoupons         = $this->usedCoupons;//已经使用优惠券列表
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        foreach ($canUseCouponList as $key => $value) {
            if ($value['useMax'] > 0) {
                $usedCouponIds   = array_column($usedCoupons, 'couponId');
                $usedCountValues = array_count_values($usedCouponIds);
                if (isset($usedCountValues[$value['couponId']])) {
                    $usedCount = $usedCountValues[$value['couponId']];
                    if ($usedCount > $value['useMax']) {
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            Log::info('pos使用优惠券错误--超过最大使用张数');
                            throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_USE_MAX,
                                $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_USE_MAX]);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }

                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤店铺
     * @param $shopId
     */
    public function filterCustomerCouponShop($type)
    {
        $canUseCouponList = $this->getCanUseCouponListByType($type);
        //获取店铺基本信息
        $shopInfo            = ShopService::getShopInfo($this->shopId);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        foreach ($canUseCouponList as $key => $value) {
            switch ($value['shopType']) {
                case CodeEnum::COUPON_SHOP_TYPE_JOIN:
                    //过滤非加盟
                    if ($shopInfo['type'] != CodeEnum::COUPON_SHOP_TYPE_JOIN) {
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            Log::info('pos使用优惠券错误--店铺非加盟不可用');
                            throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_SHOP,
                                $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_SHOP]);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                    break;
                case CodeEnum::COUPON_SHOP_TYPE_DIRECTLY:
                    //t过滤非直营
                    if ($shopInfo['type'] != CodeEnum::COUPON_SHOP_TYPE_DIRECTLY) {
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            Log::info('pos使用优惠券错误--店铺非直营不可用');
                            throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_SHOP,
                                $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_SHOP]);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                    break;
                case CodeEnum::COUPON_SHOP_TYPE_PART:
                    //过滤部分店铺
                    $shopIds = array_column($value['shopRel'], 'shopId');
                    if (!in_array($this->shopId, $shopIds)) {
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            Log::info('pos使用优惠券错误--不在部分门店内不可用');
                            throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_SHOP,
                                $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_SHOP]);;
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                    break;
                case CodeEnum::COUPON_SHOP_TYPE_ALl :
                    //全部 不做处理
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤可用商品
     */
    public function filterCustomerCouponProduct($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $productList         = $this->productList;
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        //获取产品列表的id集合
        $productListIds = array_column($productList, 'productId');
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['canUseProduct'])) {
                //todo 判断商品是可以用或者是不可以用
                if ($value['productUseType'] == CouponEnum::PRODUCT_USE_TYPE_NO) {
                    //不可使用时 先取出数据库不可适用列表
                    $notCanProductIds = explode(',', $value['canUseProduct']);
                    //比较两者差集就是可以使用的
                    $canUserProductIds = array_diff($productListIds, $notCanProductIds);
                } else {
                    $canUserProductIds = explode(',', $value['canUseProduct']);
                }
                //取交集，如果选择的商品不在可用商品范围内，过滤掉不可用的优惠券
                if (empty(array_intersect($productListIds, $canUserProductIds))) {
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        Log::info('pos使用优惠券错误--商品不可用');
                        throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_PRODUCT,
                            $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_PRODUCT]);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤日期 周一到周六以及节假日
     */
    public function filterCustomerCouponDate($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        //获取星期 1-6表示周一到周六 0 表示周末
        $day  = date("w") != 0 ? date("w") : 7;
        $date = date("Ymd");
        //获取法定节假日
        $holidayConfigList = array_column(HolidayService::getHolidayConfigList(), 'holiday');
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['unableDate'])) {
                $notUseDay = explode(',', $value['unableDate']);
                //正常周末判断
                if ($day <= 7 && in_array($day, $notUseDay)) {
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        Log::info('pos使用优惠券错误--周末不可用');
                        throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_DATE,
                            $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_DATE]);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                        continue;
                    }
                }
                //判断法定节假日
                if (in_array(CodeEnum::COUPON_UNABLE_DATE_HOLIDAY, $notUseDay) && in_array($date, $holidayConfigList)) {
                    if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                        Log::info('pos使用优惠券错误--法定节假日不可用');
                        throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_DATE,
                            $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_DATE]);
                    } else {
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤不可用时间
     * @param $type
     * @return $this
     * @throws CouponException
     */
    public function filterCustomerCouponTime($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        //获取当前时间
        $time = date('H:i:s');
        list($h, $m, $s) = explode(":", $time);
        $timeInt = ($h * 60 + $m) * 60 + $s;
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['unableTime'])) {
                $unableTime = json_decode($value['unableTime'], true);
                foreach ($unableTime as $item) {
//                    in_array($timeInt, range($item['startAt'], $item['endAt']))
                    if ($time >= $item['startAt'] && $time <= $item['endAt']) {
                        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                            Log::info('pos使用优惠券错误--时间不可用');
                            throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_TIME,
                                $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_TIME]);
                        } else {
                            $canNotUseCouponList[] = $value;
                            unset($canUseCouponList[$key]);
                        }
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤商品总金额可用
     * @return $this
     */
    public function filterCustomerCouponMoney($type)
    {
        $canUseCouponList    = $this->getCanUseCouponListByType($type);
        $productList         = $this->productList;
        $canNotUseCouponList = $this->canNotUseCouponList;//不可用优惠券列表
        $productListIds      = array_column($productList, 'productId');
        foreach ($canUseCouponList as $key => $value) {
            if (!empty($value['useCondition'])) {
                //可以使用的菜品列表集合
                $useProductIds = self::filterCanUseProductIds($value['productUseType'], $productListIds,
                    $value['canUseProduct']);
                $totalMoney    = $this->sumProductTotalMoney($productList, $useProductIds);
                if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
                    //如果是检查
                    if ($totalMoney - $this->totalCondition < $value['useCondition']) {
                        Log::info('pos使用优惠券错误--金额不满足');
                        //如果剩余可抵扣金额小于当前券条件则报错
                        throw new CouponException(CouponCodeEnum::ERR_POS_USE_COUPON_MONEY,
                            $value['name'] . ' : ' . CouponCodeEnum::CODE_TEXT[CouponCodeEnum::ERR_POS_USE_COUPON_MONEY]);
                    } else {
                        $this->totalCondition += $value['useCondition'];
                    }
                } else {
                    if ($totalMoney - $this->totalCondition < $value['useCondition']) {
                        //如果是选择，并且总金额减去总抵扣小小于当前券可抵扣
                        $canNotUseCouponList[] = $value;
                        unset($canUseCouponList[$key]);
                    }
                }
            }
        }
        $this->canNotUseCouponList = $canNotUseCouponList;
        $this->canUseCouponList    = $canUseCouponList;
        return $this;
    }

    /**
     * 过滤可用商品列表
     * @param $type
     * @param $productListIds
     * @param $canUseProduct
     * @return array|mixed
     */
    public static function filterCanUseProductIds($type, $productListIds, $canUseProduct)
    {
        if (!empty($canUseProduct)) {
            if ($type == CouponEnum::PRODUCT_USE_TYPE_NO) {
                //不可使用时 先取出数据库不可适用列表
                $notCanProductIds = explode(',', $canUseProduct);
                //比较两者差集就是可以使用的
                $canUseProduct = array_diff($productListIds, $notCanProductIds);
            } else {
                $canUseProduct = explode(',', $canUseProduct);
            }
            //获取菜品交集 走到这一步肯定是有交集的
            return array_intersect($productListIds, $canUseProduct);
        } else {
            return [];
        }
    }

    /**
     * 获取可用优惠券列表 如果是检查则是用户使用的优惠券列表
     * @param $type
     * @return $this|array
     */
    public function getCanUseCouponListByType($type)
    {
        if ($type == CodeEnum::COUPON_INIT_TYPE_CHECK) {
            $canUseCouponList = $this->usedCoupons;
        } else {
            $canUseCouponList = $this->canUseCouponList;//可用优惠券列表
            if (empty($canUseCouponList)) {
                return $canUseCouponList;
            }
        }
        return $canUseCouponList;
    }

    /**
     * 计算已抵扣金额
     * @param $usedCouponList
     * @param $productList
     */
    public function calcUsedCouponDiscount($usedCouponList, $productList)
    {
        //已抵消的商品金额
        $totalCondition = 0;
        foreach ($usedCouponList as $value) {
            switch ($value['type']) {
                case CodeEnum::COUPON_TYPE_CASH :
                    //todo 代金券
                    $totalCondition += $value['useCondition'];
                    break;
                case CodeEnum::COUPON_TYPE_EXCHANGE :
                    //todo 商品兑换券
                    break;
                case CodeEnum::COUPON_TYPE_DISCOUNT :
                    //todo 折扣券
                    break;
            }
        }
        $this->totalCondition = $totalCondition;
    }

    /**
     * 计算商品总金额
     * @param $productList
     * @param $intersect
     * @return float|int
     */
    public function sumProductTotalMoney($productList, $intersect)
    {
        $total = 0;
        if (empty($intersect)) {
            foreach ($productList as $value) {
                $total += $value['price'] * $value['number'];
            }
        } else {
            foreach ($productList as $value) {
                if (in_array($value['productId'], $intersect)) {
                    $total += $value['price'] * $value['number'];
                }
            }
        }
        return $total;
    }

    /**
     * 过滤已使用和可以使用的交集
     * @return $this
     */
    public function filterUsedCoupon($canUseCouponList)
    {
        $usedCouponList    = $this->usedCoupons;
        $usedCouponListIds = array_column($usedCouponList, 'couponCode');
        foreach ($canUseCouponList as $key => $value) {
            if (in_array($value['couponCode'], $usedCouponListIds)) {
                unset($canUseCouponList[$key]);
            }
        }
        $this->canUseCouponList = $canUseCouponList;
        return $this;
    }


}
